﻿namespace WP7Contrib.Services.BingMaps.Model
{
    using System;
    using Collections;
    using Common;
    using Common.Extensions;

    public sealed class Metadata : BaseModel, ICloneable<Metadata>
    {
        private MetadataType type;
        private string imagerUrl;
        private int imageWidth;
        private int imageHeight;
        private DateTime vintageStart;
        private DateTime vintageEnd;
        private int zoomMin;
        private int zoomMax;
        private double orientation;
        private int tilesX;
        private int tilesY;

        private ObservableCollection<string> imageUrlSubdomains;

        public Metadata()
        {
            this.imageUrlSubdomains = new ObservableCollection<string>();
        }

        public MetadataType Type
        {
            get
            {
                return this.type;
            }
            set
            {
                this.SetPropertyAndNotify(ref this.type, value, () => this.Type);
            }
        }

        public string ImagerUrl
        {
            get
            {
                return this.imagerUrl;
            }
            set
            {
                this.SetPropertyAndNotify(ref this.imagerUrl, value, () => this.ImagerUrl);
            }
        }

        public ObservableCollection<string> ImageUrlSubdomains
        {
            get
            {
                return this.imageUrlSubdomains;
            }
            set
            {
                this.SetPropertyAndNotify(ref this.imageUrlSubdomains, value, () => this.ImageUrlSubdomains);
            }
        }

        public int ImageWidth
        {
            get
            {
                return this.imageWidth;
            }
            set
            {
                this.SetPropertyAndNotify(ref this.imageWidth, value, () => this.ImageWidth);
            }
        }

        public int ImageHeight
        {
            get
            {
                return this.imageHeight;
            }
            set
            {
                this.SetPropertyAndNotify(ref this.imageHeight, value, () => this.ImageHeight);
            }
        }

        public DateTime VintageStart
        {
            get
            {
                return this.vintageStart;
            }
            set
            {
                this.SetPropertyAndNotify(ref this.vintageStart, value, () => this.VintageStart);
            }
        }

        public DateTime VintageEnd
        {
            get
            {
                return this.vintageEnd;
            }
            set
            {
                this.SetPropertyAndNotify(ref this.vintageEnd, value, () => this.VintageEnd);
            }
        }

        public int ZoomMin
        {
            get
            {
                return this.zoomMin;
            }
            set
            {
                this.SetPropertyAndNotify(ref this.zoomMin, value, () => this.ZoomMin);
            }
        }

        public int ZoomMax
        {
            get
            {
                return this.zoomMax;
            }
            set
            {
                this.SetPropertyAndNotify(ref this.zoomMax, value, () => this.ZoomMax);
            }
        }

        public double Orientation
        {
            get
            {
                return this.orientation;
            }
            set
            {
                this.SetPropertyAndNotify(ref this.orientation, value, () => this.Orientation);
            }
        }

        public int TilesX
        {
            get
            {
                return this.tilesX;
            }
            set
            {
                this.SetPropertyAndNotify(ref this.tilesX, value, () => this.TilesX);
            }
        }

        public int TilesY
        {
            get
            {
                return this.tilesY;
            }
            set
            {
                this.SetPropertyAndNotify(ref this.tilesY, value, () => this.TilesY);
            }
        }

        public bool HasImageUrlSubdomains
        {
            get { return this.imageUrlSubdomains != null && this.imageUrlSubdomains.Count != 0; }
        }

        public Metadata ShallowClone()
        {
            var metadata = new Metadata
            {
                Type = this.type,
                ImagerUrl = this.imagerUrl,
                ImageWidth = this.imageWidth,
                ImageHeight = this.imageHeight,
                ImageUrlSubdomains = this.imageUrlSubdomains,
                VintageStart = this.vintageStart,
                VintageEnd = this.vintageEnd,
                ZoomMin = this.zoomMin,
                ZoomMax = this.zoomMax
            };

            return metadata;
        }

        public Metadata DeepClone()
        {
            var metadata = new Metadata
            {
                Type = this.type,
                ImagerUrl = this.imagerUrl,
                ImageWidth = this.imageWidth,
                ImageHeight = this.imageHeight,
                VintageStart = this.vintageStart,
                VintageEnd = this.vintageEnd,
                ZoomMin = this.zoomMin,
                ZoomMax = this.zoomMax
            };

            if (this.HasImageUrlSubdomains)
            {
                var copy = new ObservableCollection<string>();
                this.imageUrlSubdomains.ForEach(copy.Add);

                metadata.ImageUrlSubdomains = copy;
            }

            return metadata;
        }
    }
}